# 一些对话框的常量
from PyPixelCore.PyPixelController import PyPixelController
from PyPixelCore.Setting import *
from PyPixelCore.animation_factory.WorkPiece import WorkPiece
from PyPixelCore.block import *
from PyPixelCore.group.BaseGroup import BaseGroup
from PyPixelCore.panel.Panel import Panel
from PyPixelCore.timer.OnlyTimer import OnlyTimer


class Dialog_Type:
    CHOOSE_DIALOG = 1  # 选择对话框
    CONFIRM_DIALOG = 2  # 确定对话框
    WARNING_DIALOG = 3  # 警告对话框
    ERROR_DIALOG = 4  # 错误对话框
    EACH_DIALOG_IMG_MAPPER = {CHOOSE_DIALOG: "recourse/system_animation_img/quest_icon.png",
                              CONFIRM_DIALOG: "recourse/system_animation_img/idea_icon.png",
                              WARNING_DIALOG: "recourse/system_animation_img/inform_icon.png",
                              ERROR_DIALOG: "recourse/system_animation_img/error_icon.png"}
    EACH_DIALOG_TEXT_MAPPER = {CHOOSE_DIALOG: "选择", CONFIRM_DIALOG: "提示", WARNING_DIALOG: "警告", ERROR_DIALOG: "错误"}
    EACH_DIALOG_COLOR_MAPPER = {CHOOSE_DIALOG: Color_type.LIGHT_BLUE, CONFIRM_DIALOG: Color_type.GREEN, WARNING_DIALOG: Color_type.YELLOW, ERROR_DIALOG: Color_type.RED}
    # open("../../recourse/system_animation_img/idea_icon.png")

class DialogFactory:
    @staticmethod
    def dialog(text_content: str, aim_controller: PyPixelController,
               yes_choice_func = None,
               no_choice_func = None,
               exit_func = None,
               image_url=None,
               draw_able=False,
               limit_w = 320,
               limit_h = 240,
               bk_color=Color_type.LOW_WHITE,
               border_color=Color_type.DEEP_GREY,
               border_width=3,
               border_width_inner=5,
               size_inner=20,
               size_window=18,
               dialog_type=Dialog_Type.CONFIRM_DIALOG):
        # 一层蒙版,告诉用户后方无法被点击
        mask = Block(width=window_width, height=window_height, layer=aim_controller.top_layer - 1,
                     bk_color=Color_type.GREY, is_alpha=True)
        mask.image.set_alpha(200)
        # 顶部的文字提示
        top_text_block = SuperMultiLineTextBlock("", limit_h=size_window + border_width, limit_w=limit_w - 30,
                                                 border_width=0, point_x=border_width, point_y=border_width)
        top_text_block.set_font(font_size=size_window)
        top_text_block.set_font_color(Dialog_Type.EACH_DIALOG_COLOR_MAPPER[dialog_type])
        top_text_block.set_bk_color(border_color)
        top_text_block.set_text_content(":" + Dialog_Type.EACH_DIALOG_TEXT_MAPPER[dialog_type])

        # 顶部的退出按钮
        exit_button = TextButton(" X ", border_width + limit_w - 30, border_width=border_width, height=size_window)
        exit_button.set_font(font_size=size_window)
        exit_button.set_bk_color(Color_type.WHITE)
        exit_button.set_border_color(border_color)
        exit_button.hover_color = Color_type.RED
        # 文字提示下方的图片
        if image_url is None: image_url = Dialog_Type.EACH_DIALOG_IMG_MAPPER[dialog_type]
        image_block = Block(50, 50, point_y=(240 - size_window) // 3 + border_width, point_x=border_width + 10)
        image_block.load_image(image_url, size_lock=True)
        # 主体框架
        dialog = Panel(0, 0, limit_w, limit_h, border_width, layer=aim_controller.top_layer, bk_color=bk_color,
                       border_color=border_color)
        # 显示内容的地方, 支持滚轮
        super_text_block = SuperMultiLineTextBlock(text_content,
                                                   limit_w=limit_w - 50 - 10 - bar_width - 2 * border_width_inner - 2 * border_width,
                                                   limit_h=limit_h - size_window - 2 * border_width_inner,
                                                   point_x=border_width + 50 + 10 + 2 * border_width_inner + border_width,
                                                   point_y=top_text_block.rect.bottom, border_width=border_width_inner)
        super_text_block.set_color_no_None(bk_color=bk_color, border_color=bk_color)
        super_text_block.set_font(font_size=size_inner)
        super_text_block.set_text_content(text_content)
        super_text_block.interval = super_text_block.real_height - super_text_block.limit_h
        super_text_block.load_height = super_text_block.limit_h
        super_text_block.set_limit_size(super_text_block.limit_w, super_text_block.real_height)
        bar_height = (super_text_block.load_height / super_text_block.real_height) * (
                    limit_h - size_window) if super_text_block.real_height / super_text_block.load_height > 1 else (
                    limit_h - size_window)
        # bar滚轮组件
        text_bar = Bar(border_width + limit_w - bar_width, point_y=top_text_block.rect.bottom,
                       real_height=limit_h - size_window, bar_height=bar_height, border_width=0)

        def bar_lind_do(self: Bar):
            super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval * self.bar_process
            super_text_block.is_dirty = True

        text_bar.stream_move_link = bar_lind_do
        # 美化用的蒙版
        shader_mask = Block(point_y=border_width + size_window, point_x=border_width, width=70,
                            height=limit_h - size_window, bk_color=Color_type.LIGHT_GREY)

        # 如果是# 选择对话框则额外添加取消按钮
        correct_height_split = (limit_h + border_width - image_block.rect.center[1]) // 6
        cancel_block = None
        if dialog_type == Dialog_Type.CHOOSE_DIALOG:
            # 确定按钮
            confirm_block = TextButton("确定")
            confirm_block.rect.center = image_block.rect.center
            confirm_block.rect.y += correct_height_split * 2.5
            # 取消按钮
            cancel_block = TextButton("取消")
            cancel_block.rect.center = image_block.rect.center
            cancel_block.rect.y += correct_height_split * 4
            cancel_block.collision_rect.center = cancel_block.rect.center
        else:
            # 确定按钮
            confirm_block = TextButton("确定")
            confirm_block.rect.center = image_block.rect.center
            confirm_block.rect.y += correct_height_split * 3.5
        dialog.add_sprites(shader_mask,confirm_block,cancel_block,image_block, super_text_block, top_text_block, text_bar, exit_button)
        confirm_block.collision_rect.center = confirm_block.rect.center

        dialog.load_pos = (-1, -1)
        dialog.is_moveable = False
        dialog.is_inner_moveable = False

        def clicked_animation(self: Panel, pos):
            if draw_able:
                if top_text_block.collision_rect.collidepoint(pos):
                    dialog.is_moveable = True
                    dialog.load_pos = pos
            if super_text_block.collision_rect.collidepoint(pos): dialog.is_inner_moveable = True
            if not dialog.is_focus:
                dialog.is_focus = True

        def motion_animation(self: Panel, pos):  # 拖动框或者拖动其他
            if dialog.is_moveable:
                offset_x = pos[0] - dialog.load_pos[0]
                offset_y = pos[1] - dialog.load_pos[1]
                dialog.load_pos = pos
                dialog.change_point_by_offset(offset_x, offset_y)
            elif dialog.is_inner_moveable:
                text_bar.stream_move(pos)

        def up_clicked_animation(self: Panel):
            dialog.is_moveable = False
            dialog.is_inner_moveable = False
            text_bar.before_pos = None

        def wheel_down_animation(self):
            if text_bar.real_height - text_bar.bar_height == 0:  return
            if text_bar.bar_process == 0:  return
            process_add = bar_sensitive / super_text_block.real_height
            text_bar.bar_process -= process_add
            if text_bar.bar_process < 0:
                text_bar.bar_process = 0.0
            text_bar.is_dirty = True
            super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval * text_bar.bar_process

        def wheel_up_animation(self):
            if text_bar.real_height - text_bar.bar_height == 0:  return
            if text_bar.bar_process == 1:  return
            process_add = bar_sensitive / super_text_block.real_height
            text_bar.bar_process += process_add
            if text_bar.bar_process > 1:
                text_bar.bar_process = 1
            text_bar.is_dirty = True
            super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval * text_bar.bar_process

        dialog.wheel_up_animation_do = wheel_up_animation
        dialog.wheel_down_animation_do = wheel_down_animation
        dialog.focus_animation_do = clicked_animation
        dialog.focus_motion_animation_do = motion_animation
        dialog.mouse_up_do = up_clicked_animation

        dialog.change_point_x_y((window_width - dialog.width) // 2, (window_height - dialog.height) // 2)


        def work_piece_run_func(self:WorkPiece,controller):
            if cancel_block:
                def cancel_func(self):
                    if no_choice_func: no_choice_func()
                    exit_dialog()
                cancel_block.set_click_up_func(cancel_func)
            def yes_func(self):
                if yes_choice_func: yes_choice_func()
                exit_dialog()
            confirm_block.set_click_up_func(yes_func)
            dialog.add_sprites(shader_mask,confirm_block,cancel_block,image_block, super_text_block, top_text_block, text_bar, exit_button)

            controller.add_block(dialog)
            save_clicked_sprites = controller.groups_manager.click_able_sprites
            save_focus_sprites = controller.groups_manager.focus_able_sprites
            # 设置交互变量为当前框
            controller.groups_manager.click_able_sprites = BaseGroup()
            controller.groups_manager.focus_able_sprites = BaseGroup()
            controller.groups_manager.add_block_repeat(dialog, mask)
            controller.groups_manager.print_all_groups()
            def exit_dialog():
                controller.groups_manager.click_able_sprites = save_clicked_sprites
                controller.groups_manager.focus_able_sprites = save_focus_sprites
                mask.kill()
                dialog.kill()
            def exit_button_do(self):
                if exit_func: exit_func()
                exit_dialog()
            exit_button.set_click_up_func(exit_button_do)
            if controller.focus_block:  controller.focus_block.leave_focus_animation((-1, -1))  # 可能会引发错误
            dialog.focus_animation((-1, -1))
            controller.focus_block = dialog
            if controller.hovered_button: controller.hovered_button.mouse_hover_leave()
            controller.hovered_button = None
            controller.clicked_button = None
        piece = WorkPiece(dialog, mask, run_func=work_piece_run_func)
        return piece


# 提醒框动画, 展示(模态)提醒框,需要点击按钮才能消失(不维护)
def inform_dialog_animation(text_content: str, aim_controller: PyPixelController,
                            yes_choice_func = None,
                            no_choice_func = None,
                            exit_func = None,
                            image_url=None,
                            draw_able=False,
                            limit_w = 320,
                            limit_h = 240,
                            bk_color=Color_type.LOW_WHITE,
                            border_color=Color_type.DEEP_GREY,
                            border_width=3,
                            border_width_inner=5,
                            size_inner=20,
                            size_window=18,
                            dialog_type=Dialog_Type.CONFIRM_DIALOG):
    # 一层蒙版,告诉用户后方无法被点击
    mask = Block(width=window_width,height=window_height,layer=aim_controller.top_layer-1,bk_color=Color_type.GREY,is_alpha=True)
    mask.image.set_alpha(200)
    # 顶部的文字提示
    top_text_block = SuperMultiLineTextBlock("", limit_h=size_window+border_width, limit_w=limit_w - 30, border_width=0, point_x=border_width, point_y=border_width)
    top_text_block.set_font(font_size=size_window)
    top_text_block.set_font_color(Dialog_Type.EACH_DIALOG_COLOR_MAPPER[dialog_type])
    top_text_block.set_bk_color(border_color)
    top_text_block.set_text_content(":" + Dialog_Type.EACH_DIALOG_TEXT_MAPPER[dialog_type])

    # 顶部的退出按钮
    exit_button = TextButton(" X ",border_width+limit_w-30,border_width=border_width,height=size_window)
    exit_button.set_font(font_size=size_window)
    exit_button.set_bk_color(Color_type.WHITE)
    exit_button.set_border_color(border_color)
    exit_button.hover_color = Color_type.RED
    # 文字提示下方的图片
    if image_url is None: image_url = Dialog_Type.EACH_DIALOG_IMG_MAPPER[dialog_type]
    image_block = Block(50, 50, point_y=(240 - size_window) // 3 + border_width, point_x=border_width + 10)
    image_block.load_image(image_url, size_lock=True)
    # 主体框架
    dialog = Panel(0,0,limit_w,limit_h,border_width,layer=aim_controller.top_layer,bk_color=bk_color,border_color=border_color)
    # 显示内容的地方, 支持滚轮
    super_text_block = SuperMultiLineTextBlock(text_content, limit_w=limit_w - 50 - 10 - bar_width-2*border_width_inner-2*border_width,
                                               limit_h=limit_h-size_window-2*border_width_inner, point_x=border_width + 50 + 10 + 2*border_width_inner+border_width,
                                               point_y=top_text_block.rect.bottom, border_width=border_width_inner)
    super_text_block.set_color_no_None(bk_color=bk_color,border_color=bk_color)
    super_text_block.set_font(font_size=size_inner)
    super_text_block.set_text_content(text_content)
    super_text_block.interval = super_text_block.real_height - super_text_block.limit_h
    super_text_block.load_height = super_text_block.limit_h
    super_text_block.set_limit_size(super_text_block.limit_w, super_text_block.real_height)
    bar_height =  (super_text_block.load_height / super_text_block.real_height) * (limit_h - size_window) if super_text_block.real_height / super_text_block.load_height > 1 else (limit_h - size_window)
    # bar滚轮组件
    text_bar = Bar(border_width + limit_w - bar_width, point_y=top_text_block.rect.bottom, real_height=limit_h - size_window,bar_height=bar_height, border_width=0)
    def bar_lind_do(self: Bar):
        super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval*self.bar_process
        super_text_block.is_dirty = True
    text_bar.stream_move_link = bar_lind_do
    # 美化用的蒙版
    shader_mask = Block(point_y=border_width+size_window,point_x=border_width,width=70,height=limit_h-size_window,bk_color=Color_type.LIGHT_GREY)
    dialog.add_sprites(shader_mask)

    # 如果是# 选择对话框则额外添加取消按钮
    correct_height_split = (limit_h+border_width-image_block.rect.center[1]) // 6
    if dialog_type == Dialog_Type.CHOOSE_DIALOG:
        # 确定按钮
        confirm_block = TextButton("确定")
        confirm_block.rect.center = image_block.rect.center
        confirm_block.rect.y += correct_height_split * 2.5
        # 取消按钮
        cancel_block = TextButton("取消")
        cancel_block.rect.center = image_block.rect.center
        cancel_block.rect.y += correct_height_split * 4
        cancel_block.collision_rect.center = cancel_block.rect.center
        dialog.add_sprites(confirm_block, cancel_block)
        def cancel_func(self):
            if no_choice_func: no_choice_func()
            exit_dialog()
        cancel_block.set_click_up_func(cancel_func)
    else:
        # 确定按钮
        confirm_block = TextButton("确定")
        confirm_block.rect.center = image_block.rect.center
        confirm_block.rect.y += correct_height_split * 3.5
        dialog.add_sprites(confirm_block)

    def yes_func(self):
        if yes_choice_func: yes_choice_func()
        exit_dialog()
    confirm_block.set_click_up_func(yes_func)
    confirm_block.collision_rect.center = confirm_block.rect.center
    dialog.add_sprites(image_block, super_text_block, top_text_block, text_bar, exit_button)
    # 临时保存交互变量
    aim_controller.add_block(dialog)
    save_clicked_sprites = aim_controller.groups_manager.click_able_sprites
    save_focus_sprites = aim_controller.groups_manager.focus_able_sprites

    # 设置交互变量为当前框
    aim_controller.groups_manager.click_able_sprites = BaseGroup()
    aim_controller.groups_manager.focus_able_sprites = BaseGroup()
    aim_controller.groups_manager.add_block_repeat(dialog, mask)

    aim_controller.groups_manager.print_all_groups()

    def exit_dialog():
        print("点击退出")
        aim_controller.groups_manager.click_able_sprites = save_clicked_sprites
        aim_controller.groups_manager.focus_able_sprites = save_focus_sprites
        dialog.kill()
        mask.kill()
    def exit_button_do(self):
        if exit_func: exit_func()
        exit_dialog()
    exit_button.set_click_up_func(exit_button_do)

    dialog.load_pos = (-1, -1)
    dialog.is_moveable = False
    dialog.is_inner_moveable = False
    def clicked_animation(self: Panel, pos):
        if draw_able:
            if top_text_block.collision_rect.collidepoint(pos):
                dialog.is_moveable = True
                dialog.load_pos = pos
        if super_text_block.collision_rect.collidepoint(pos): dialog.is_inner_moveable = True
        if not dialog.is_focus:
            dialog.is_focus = True
    def motion_animation(self: Panel, pos):  # 拖动框或者拖动其他
        if dialog.is_moveable:
            offset_x = pos[0] - dialog.load_pos[0]
            offset_y = pos[1] - dialog.load_pos[1]
            dialog.load_pos = pos
            dialog.change_point_by_offset(offset_x,offset_y)
        elif dialog.is_inner_moveable:
            text_bar.stream_move(pos)

    def up_clicked_animation(self: Panel):
        dialog.is_moveable = False
        dialog.is_inner_moveable = False
        text_bar.before_pos = None

    def wheel_down_animation(self):
        if text_bar.real_height - text_bar.bar_height == 0:  return
        if text_bar.bar_process == 0:  return
        process_add = bar_sensitive / super_text_block.real_height
        text_bar.bar_process -= process_add
        if text_bar.bar_process < 0:
            text_bar.bar_process = 0.0
        text_bar.is_dirty = True
        super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval*text_bar.bar_process

    def wheel_up_animation(self):
        if text_bar.real_height - text_bar.bar_height == 0:  return
        if text_bar.bar_process == 1:  return
        process_add = bar_sensitive / super_text_block.real_height
        text_bar.bar_process += process_add
        if text_bar.bar_process > 1:
            text_bar.bar_process = 1
        text_bar.is_dirty = True
        super_text_block.rect.y = top_text_block.rect.bottom - super_text_block.interval*text_bar.bar_process

    dialog.wheel_up_animation_do = wheel_up_animation
    dialog.wheel_down_animation_do = wheel_down_animation
    dialog.focus_animation_do = clicked_animation
    dialog.focus_motion_animation_do = motion_animation
    dialog.mouse_up_do = up_clicked_animation

    dialog.change_point_x_y((window_width-dialog.width)//2, (window_height-dialog.height)//2)
    def end_thing(self):
        if self.focus_block:  self.focus_block.leave_focus_animation((-1,-1))  # 可能会引发错误
        dialog.focus_animation((-1,-1))
        self.focus_block = dialog
    aim_controller.add_controller_timer_animation(OnlyTimer(1),end_thing)



